import Element from '../element';
import Utils from '../Utils/Utils';
import TagValidate from '../Validate/TagValidate';
import { AST_NODE_TYPE, HTML_TAG_EVENT_TYPE, ERROR_TYPE, nooper } from '../constant';

export default class TagParser {

    htmlTag = undefined;
    element = undefined;

    constructor () {
    }

    // 生命周期 初始化
    init (htmlTag) {
        this.htmlTag = htmlTag;
        this.element = new Element();
        this.element.astType = AST_NODE_TYPE.NODE;
    }

    // 生命周期 销毁
    destroy () {
        this.htmlTag = undefined;
        this.element = undefined;
    }

    /**
     * 整个分析流程模板，对外API
     * @param {String} htmlTag 
     * @param {String} htmlTagType
     */
    parse (htmlTag) {
        this.init(htmlTag)
        this.parseTagType();
        this.parseTagProperty();
        this.parseTagEvent();
        let element = this.element;
        this.destroy();
        return element;
    }

    /**
     * 分析得到 标签字符串的 标签类型
     */
    parseTagType () {
        let matcher = /\<\s*[a-zA-Z0-9]+/;
        let matchResult = this.htmlTag.match(matcher);
        if ( !Utils.isNull(matchResult) )  {
            let matchStr = matchResult[0];
            let start = 1;
            while (matchStr[start] === ' ') {
                start ++;
            }
            let type = matchStr.substring(start, matchStr.length);

            TagValidate.isValidTagType(type);
            this.element.type = type;

            this.htmlTag = this.htmlTag.replace(matchStr, "");
        } else {
            let exception = new Error(
                `发现一个无法分析标签类型的标签，是否使用了非法的书写方式？
                标签为: ${htmlTag}
                分析字符串至: ${this.htmlStr}`
            );
            exception.type = ERROR_TYPE.INVALID_TAG_TYPE;
            throw exception;
        }
    }

    /**
     * 分析得到 标签字符串的 标签属性
     */
    parseTagProperty () {
        let propertyEntryMatcher = /\s[^=<>\s'"\/]+(\s*=\s*(\'[^=<>\/]*\'|\"[^=<>\/]*\"))?/g;
        let propertyEntryList = this.htmlTag.match(propertyEntryMatcher);
        while (propertyEntryList && propertyEntryList.length !== 0) {
            let propertyEntryStr = propertyEntryList.pop();
            let nameMatcher = /\s[^=<>\s'"\/]+/;
            let singleValueMatcher = /\=\s*\'[^=<>\/]*\'/;
            let doubleValueMatcher = /\=\s*\"[^=<>\/]*\"/;

            let name = propertyEntryStr.match(nameMatcher)[0];
            let singleValueMatchResult = propertyEntryStr.match(singleValueMatcher);
            let doubleValueMatchResult = propertyEntryStr.match(doubleValueMatcher);
            if ( !Utils.isNull(singleValueMatchResult) ) {
                let valueStr = singleValueMatchResult[0];
                let start = valueStr.indexOf('\'');
                let finish = valueStr.lastIndexOf('\'');
                
                let value = valueStr.substring(start+1, finish);
                this.element.attributes.set(name.trim(), value);
            } 
            else if ( !Utils.isNull(doubleValueMatchResult) ) {
                let valueStr = doubleValueMatchResult[0];
                let start = valueStr.indexOf('\"');
                let finish = valueStr.lastIndexOf('\"');
                
                let value = valueStr.substring(start+1, finish);
                this.element.attributes.set(name.trim(), value.trim());
            }
            else {
                this.element.attributes.set(name.trim(), nooper);
                // do nothing
            }
        }
    }

    /**
     * 将 property 中的事件全部放置到 event 中
     */
    parseTagEvent () {
        this.element.attributes.forEach(function(value, name) {
            if (HTML_TAG_EVENT_TYPE.has(name)) {
                this.element.events.set(name, value);
                this.element.attributes.delete(name);
            }
        }.bind(this));
    }

};